use std::{rc::Rc, cell::RefCell};

use crate::{native, rtda::{Frame, heap::string_pool}};

pub fn init() {
    native::register("java/lang/ClassLoader", "findLoadedClass0", "(Ljava/lang/String;)Ljava/lang/Class;", find_loaded_class0);
    native::register("java/lang/ClassLoader", "findBootstrapClass", "(Ljava/lang/String;)Ljava/lang/Class;", find_bootstrap_class);
}

// TODO 231121 目前只有一个类加载器，后续调整。
// private native final Class<?> findLoadedClass0(String name);
// (Ljava/lang/String;)Ljava/lang/Class;
fn find_loaded_class0(frame: Rc<RefCell<Frame>>) {
    // 获取this引用，等同于get_ref(0)
    // let this = frame.borrow().get_local_vars().borrow().get_this().unwrap();
    let name_obj = frame.borrow().get_local_vars().borrow().get_ref(1);
    let name = string_pool::rs_string(name_obj.unwrap());
    let name = handle_name(name);
    let loader = frame.borrow().get_method().get_class().get_class_loader().unwrap();
    let class = loader.lock().unwrap().get_class(name);
    let j_class = match class {
        Some(c) => c.get_j_class(),
        None => None
    };
    frame.borrow().get_operand_stack().borrow_mut().push_ref(j_class);
}

// TODO 231121 目前只有一个类加载器，后续调整。
// 返回由引导类加载器加载的类;如果未找到，则返回 null。
// private native Class<?> findBootstrapClass(String name);
// (Ljava/lang/String;)Ljava/lang/Class;
fn find_bootstrap_class(frame: Rc<RefCell<Frame>>) {
    // 获取this引用，等同于get_ref(0)
    // let this = frame.borrow().get_local_vars().borrow().get_this().unwrap();
    let name_obj = frame.borrow().get_local_vars().borrow().get_ref(1);
    let name = string_pool::rs_string(name_obj.unwrap());
    let name = handle_name(name);
    let loader = frame.borrow().get_method().get_class().get_class_loader().unwrap();
    // TODO 231121 未处理未找到类的情况
    let class = loader.lock().unwrap().load_class(name);

    frame.borrow().get_operand_stack().borrow_mut().push_ref(class.get_j_class());
}

fn handle_name(name: String) -> String {
    if name.ends_with(".class") {
        name[0..name.len() - 5].replace(".", "/")
    } else {
        name.replace(".", "/")
    }
}